﻿using System;
using System.IO;
using System.Text;
using System.Threading;
using System.Collections.Generic;

namespace COUP.Core.Files
{
    public static class GameMap
    {
        static Dictionary<int, Map> Maps = new Dictionary<int,Map>();
        static Dictionary<int, Thread> Threads = new Dictionary<int, Thread>(5);
        static Queue<int> MapQueue = new Queue<int>();

        public static int ConsoleTop = 1;

        public static Dictionary<int, Map> Parse()
        {            
            Dictionary<int, Thread> Threads = new Dictionary<int,Thread>(5);

            using (FileStream File = new FileStream(Settings.GameMap, FileMode.Open))
            {
                using (BinaryReader Reader = new BinaryReader(File))
                {
                    Monitor.Enter(Console.Out);
                    Console.Write("[Game Server] Loading Map....");
                    Console.CursorVisible = false;

                    int MapCount = Reader.ReadInt32();

                    for (int i = 0; i < MapCount; i++)
                    {                        
                        int MapID = Reader.ReadInt32();

                        File.Seek(Reader.ReadInt32(), SeekOrigin.Current);

                        if (MapQueue.Contains(MapID) || Maps.ContainsKey(MapID))
                        {
                            File.Seek(4, SeekOrigin.Current);
                            continue;
                        }                       

                        File.Seek(4, SeekOrigin.Current);

                        MapQueue.Enqueue(MapID);
                    }

                    Monitor.Exit(Console.Out);

                    int x = 0;

                    while (MapQueue.Count != 0 || Threads.Count != 0)
                    {
                        if (MapQueue.Count != 0 && Threads.Count < 5)
                        {
                            int MapID = MapQueue.Dequeue();
                            Threads.Add(x, new Thread(new ParameterizedThreadStart(Worker)));
                            Threads[x].Start(MapID);
                            x++;
                        }
                        else
                        {
                            for (int i = 0; i < x; i++)
                            {
                                if(!Threads.ContainsKey(i))
                                    continue;

                                if (Threads[i].ThreadState == ThreadState.Stopped && !Threads[i].IsAlive)
                                    Threads.Remove(i);
                            }
                        }
                    }
                }
            }
            while (!Monitor.TryEnter(Console.Out, 500)) { }
            Console.Write("Complete");
            Console.SetCursorPosition(0, ConsoleTop);
            Monitor.PulseAll(Console.Out);
            Monitor.Exit(Console.Out);
            return Maps;
        }

        internal static void Worker(object Data)
        {
            Maps.Add((int)Data, new Map((int)Data));

            if (Maps[(int)Data]._width == 0 || Maps[(int)Data]._height == 0)
                Maps.Remove((int)Data);
        }
    }
}
